﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using AMS.DataAccess.Sql;
using System.Reflection;

namespace AMS.DataAccess.Dao
{
    /// <summary>
    /// 所有DAO类的基类
    /// </summary>
    /// <typeparam name="T">必需是带有数据库信息的业务实体</typeparam>
    public abstract class DaoBase<T> : IBusinessObjectDao<T>
        where T : class
    {
        private string tableName;

        /// <summary>
        /// 获取或设置表名
        /// </summary>
        protected virtual string TableName
        {
            set { tableName = value; }
            get
            {
                if (!IsNullOrWhiteSpace(tableName))
                {
                    return tableName;
                }

                ObjectInfo objectInfo = ObjectUtils.GetBOObjectInfo<T>();
                if (objectInfo.TableInfo != null)
                {
                    if (!IsNullOrWhiteSpace(objectInfo.TableInfo.TableName))
                    {
                        return objectInfo.TableInfo.TableName;
                    }
                    else
                    {
                        return typeof(T).Name;
                    }
                }

                return null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        static bool IsNullOrWhiteSpace(string value)
        {
            return string.IsNullOrEmpty(value) || value.Trim() == string.Empty;
        }

        /// <summary>
        /// 运行SQL功能的适配器
        /// </summary>
        protected abstract ISqlAdapter SqlAdapter { get; }

        /// <summary>
        /// 将一个实体插入到数据库表中.
        /// 对于含 id
        /// </summary>
        /// <param name="bo"></param>
        /// <returns></returns>
        public virtual int Add(T bo)
        {
            ObjectInfo boInfo = ObjectUtils.GetBOObjectInfo<T>();
            PropertyInfo property = GetIdentityProperty(bo);
            if (property == null)
            {
                SqlInsert insert = new SqlInsert(TableName);
                insert.AddBusinessObject(bo);
                string sql = insert.ToString();
                return SqlAdapter.ExecuteSql(sql);
            }
            else
            {
                return AddBOWithIdentity(bo, property);
            }
        }

        /// <summary>
        /// 对于带有 IDENTITY 列的对象的添加，返回对象的新的IDENTITY值，仅适用于 SQL SERVER
        /// </summary>
        /// <param name="bo"></param>
        /// <returns></returns>
        protected virtual int AddBOWithIdentity(T bo, PropertyInfo property)
        {
            SqlBatch batch = new SqlBatch();
            var insert = batch.CreateSqlInsert(TableName);
            insert.AddBusinessObject(bo);

            var sb = batch.CreateSqlBuilder();
            sb.Add("SELECT @@IDENTITY");

            string sql = batch.ToString();
            var ds = SqlAdapter.Query(sql);
            if (ds.Tables[0].Rows.Count > 0)
            {
                int newId = Convert.ToInt32(ds.Tables[0].Rows[0][0]);
                property.SetValue(bo, newId, null);
                return newId;
            }

            return 0;
        }

        /// <summary>
        /// 获取是 IDENTITY 列的信息
        /// </summary>
        /// <param name="bo"></param>
        /// <returns></returns>
        private PropertyInfo GetIdentityProperty(T bo)
        {
            ObjectInfo objectInfo = ObjectUtils.GetBOObjectInfo(bo.GetType());
            foreach (PropertyInfo property in objectInfo.PKFields)
            {
                object[] attributes = property.GetCustomAttributes(typeof(DBPrimaryKeyColumnAttribute), true);
                if (((DBPrimaryKeyColumnAttribute)(attributes[0])).IsIdentity)
                {
                    return property;
                }
            }

            return null;
        }

        /// <summary>
        /// 更新一个数据库表
        /// </summary>
        /// <param name="bo"></param>
        /// <returns></returns>
        public virtual int Update(T bo)
        {
            SqlUpdate update = new SqlUpdate(TableName);
            update.AddBusinessObject(bo);
            update.AddPrimaryKeyFieldAsCondition(bo);

            string sql = update.ToString();
            return SqlAdapter.ExecuteSql(sql);
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="bo"></param>
        /// <returns></returns>
        public virtual int Delete(T bo)
        {
            SqlDelete delete = new SqlDelete(TableName);
            delete.AddPrimaryKeyFieldAsCondition(bo);

            string sql = delete.ToString();
            return SqlAdapter.ExecuteSql(sql);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public virtual List<T> GetList()
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT * FROM ");
            sql.Add(TableName);

            var ds = SqlAdapter.Query(sql.ToString());
            return BusinessObjectMapping.DataTableToBOList<T>(ds.Tables[0]);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public virtual List<T> GetList(string filter, string sort)
        {
            return GetList("*", filter, sort);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public virtual List<T> GetList(string columns, string filter, string sort)
        {
            var dt = GetTable(columns, filter, sort);
            return BusinessObjectMapping.DataTableToBOList<T>(dt);
        }

        /// <summary>
        /// 获取列表信息
        /// </summary>
        /// <returns></returns>
        public virtual DataTable GetTable()
        {
            return GetTable("*", null, null);
        }

        /// <summary>
        /// 获取列表信息
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public virtual DataTable GetTable(string filter, string sort)
        {
            return GetTable("*", filter, sort);
        }

        /// <summary>
        /// 获取列表信息
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public virtual DataTable GetTable(string columns, string filter, string sort)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT ");
            sql.Add(IsNullOrWhiteSpace(columns) ? "*" : columns);
            sql.Add("FROM ");
            sql.Add(TableName);
            if (!IsNullOrWhiteSpace(filter))
            {
                sql.Add("WHERE ", filter);
            }
            if (!IsNullOrWhiteSpace(sort))
            {
                sql.Add("ORDER BY ", sort);
            }

            var ds = SqlAdapter.Query(sql.ToString());
            return ds.Tables[0];
        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="filter">筛选的条件</param>
        /// <returns></returns>
        public virtual T GetModel(string filter)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT * FROM ");
            sql.Add(TableName);
            if (!IsNullOrWhiteSpace(filter))
            {
                sql.Add("WHERE ", filter);
            }

            var ds = SqlAdapter.Query(sql.ToString());
            if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
            {
                return BusinessObjectMapping.DataRowToBO<T>(ds.Tables[0].Rows[0]);
            }

            return null;
        }

        /// <summary>
        /// 查询并返回列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual List<T> Query<T>(string sql)
        {
            var ds = SqlAdapter.Query(sql.ToString());
            if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
            {
                return BusinessObjectMapping.DataTableToBOList<T>(ds.Tables[0]);
            }

            return null;
        }
    }
}
